package com.fingard.dsp.bank.directbank.scb02;

import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.bankInterface.IBalance;
import com.fingard.dsp.bank.reqrespobj.balance.Req7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.Req7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsBalDetail;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsHisBalDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;

/**
 * @author XueJy on 2018/8/2.
 * @version 1.0
 */
public class SCB02Balance extends SCB02Base implements IBalance {
    /**
     * 渣打银行今日余额查询
     * C#版本转java
     */
    @Override
    public RetAts7506BalQry d_7506_BalQry(Req7506BalQry p_req7506) throws Exception {
        //查询账号
        String actNum = "";
        //查询币种
        String actCur = "";
        String actArea = "";
        //唯一流水号
        String reqSeqId = p_req7506.reqHeader.transSeqID;
        //创建返回对象
        RetAts7506BalQry retAts = new RetAts7506BalQry(p_req7506.reqHeader);

//        p_req7506.reqHeader.transTime=formatTimeEight(p_req7506.reqHeader.transTime);//把时间加8小时


        //写返回ATS的统一头部信息
        retAts.writeStart();
        SimpleDateFormat generatedFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ssZ", Locale.US);
        int batchNum = 0;
        //D:\Workspaces\FilesForDevelop\BankPort\SCB02\host2host\documents\reportscust\out\actbalenq-req\
        String balanceRequestPath = getH2HPath("BalanceRequestFilePath");//渣打银行client接收来自DSP发送余额查询文件所存放的路径
        //读取配置文件CSV文件导出的路径、//历史余额根据日结即每日交易明细信息获取余额信息
        //D:\Workspaces\FilesForDevelop\BankPort\SCB02\host2host\documents\reportscust\in\txn\
        String balanceFilePath = getH2HPath("ReceiveSCBTodayBalanceFilePath");//渣打银行client接收来自渣打银行SCB回盘当日余额文件所存放的路径
        //D:\Workspaces\SCB02\reportscust\in\txn\
        String localBalFilePath = getH2HPath("localBalFilePath");//余额明细流水查询本地保存路径
//        folderToFolder(balanceFilePath, localBalFilePath);

//        copyDirectiory(balanceFilePath,localBalFilePath);
//        if (!delAllFile(localBalFilePath)) {
////            WriteBankLogLn("删除本地文件失败");
//        }
        copyDirectiory(balanceFilePath, localBalFilePath);
        if (!delAllFile(balanceFilePath)) {
//            WriteBankLogLn("删除银行返回文件失败");
        }

        while (p_req7506.readRecord()) {
            RetAtsBalDetail detail = new RetAtsBalDetail();
            actNum = p_req7506.readedDetail.actNum;
            actCur = convertCurToBank(p_req7506.readedDetail.actCur);
            actArea = p_req7506.readedDetail.actArea;
            detail.actArea = actArea;
            detail.actNum = actNum;
            try {
                Boolean isok = false;//查询成功标志
                String[] arr = new String[10];//记录要删除的已经查过的文件名
                int n = 0;//记录要删除的已经查过的文件数
                // 读取银行返回余额文件信息，组装报文发给ATS
                //读取配置文件CSV文件导出的路径
//                String datePath = Format.Date8Format.format(new Date());
//                String fileDatePath = getTrimPath(localBalFilePath) + File.separator + datePath.substring(0, 6) + File.separator + datePath.substring(6, 8);
//                List<String> fileNames = getDirectoryAllFileName(fileDatePath);
                List<String> fileNames = getDirectoryAllFileName(localBalFilePath);
                if (fileNames.size() == 0) {//银行返回文件数为0或复制文件失败
//                    detail.respCode = "-1";
//                    detail.respInfo = "银行还没返回文件，或文件复制失败";
//                    retAts.writeRetDetail(detail, p_req7506.isBatch);
                    WriteBankLogLn("银行还没返回文件，或文件复制失败");
//                    retAts.writeEnd();
//                    return retAts;
                }
                //当前余额
                String currBal = "0.00";
                //可用余额
                String availBal = "0.00";
                //交易余额日期
                String lastTranDate = "";
                boolean isCheckBalance = false;
                List<String[]> actBalances = new ArrayList<String[]>();
                for (String filename : fileNames) {
//                    String fullBalancePath = getTrimPath(fileDatePath) + File.separator + filename;
                    String fullBalancePath = getTrimPath(localBalFilePath) + File.separator + filename;
                    synchronized (this) {
                        boolean requireDelete = false;
                        String strline;
                        InputStream inputStream = new FileInputStream(fullBalancePath);
                        BufferedReader mysr = new BufferedReader(new InputStreamReader(inputStream, getCharset()));
                        while ((strline = mysr.readLine()) != null) {
                            String[] aryline = splitStringWithComma(strline);
                            if (aryline.length > 15) {
                                //if (StringHelper.isNullOrEmpty(aryline[9])) continue;//此处为空或格式不正确需抛异常，因此不做空处理
                                if (StringHelper.isNullOrEmpty(aryline[9]) || !StringHelper.isNullOrEmpty(aryline[15])) {
                                    if (aryline[5].equals(actNum)) {
                                        requireDelete = true;
                                    }
                                    break;
                                } else {
                                    Date businessDate = sdf.parse(aryline[9]);
                                    //30/01/2019 08:19:37+0800
                                    if ("BAL".equals(aryline[0]) && aryline[5].equals(actNum) && aryline[14].substring(0, 10).equals(sdf.format(new Date()))) {
//                                    if (true) {//测试用
                                        WriteBankLogStep3(strline);
                                        if (StringHelper.isNullOrEmpty(aryline[11])) {
                                            //最后总余额返回报文信息中为空异常，则默认赋值0.00
                                            aryline[11] = "0.00";
                                        }
                                        if (StringHelper.isNullOrEmpty(aryline[13])) {
                                            //最后可用余额返回报文信息中为空异常，则默认赋值0.00
                                            aryline[13] = "0.00";
                                        }
                                        actBalances.add(new String[]{
                                                aryline[14], Format.Date10Format.format(businessDate), aryline[11], aryline[13]});

                                        n++;
                                        arr[n] = fullBalancePath;
                                        isok = true;

                                    }
                                }
                            } else {
                                WriteBankLogLn("账号余额查询：" + filename + "文件中余额信息格式不正确");
                            }
                        }
                        mysr.close();
                        inputStream.close();

                        for(int i = 1;i<=n;i++){
                            File file = new File(arr[i]);
                            deleteFile(file);
                        }

                        //异常格式的余额文件处理
                        if (requireDelete) {
                            File excpFile = new File(fullBalancePath);
                            if (excpFile.exists()) {
                                //备份异常格式余额信息文件路径
                                String bakDirectory = FGBiz.DSPHOME + File.separator + "backup\\SCB02\\exceptionbalancebak\\";
                                //移除异常格式文件到备份目录
                                copyFile(fullBalancePath, bakDirectory);
                                excpFile.delete();
                            }
                        }
                    }
                }
                //查询获取最新余额信息，若不存在此账号余额信息或余额信息时间在1小时之前，则生成余额查询文件获取新的余额信息
                // String[] item = actBalances.FirstOrDefault(o = > o[0] == actBalances.Max(c = > c[0]));
                String[] item = null;
                if (actBalances != null && actBalances.size() > 0) {
//                    item = actBalances.get(0);
                    item = actBalances.get(actBalances.size()-1);
                    for (String[] recent : actBalances) {
                        if (generatedFormat.parse(item[0]).getTime() < generatedFormat.parse(recent[0]).getTime()) {
                            item = recent;
                        }
                    }
                }
                if (item != null) {
                    lastTranDate = item[1];
                    currBal = item[2];
                    availBal = item[3];
                    //根据报告产生日期时间判断当日余额时间段 16/05/2015 09:32:31+0800
                    Date generatedDate = generatedFormat.parse(item[0]);
                    Calendar nowDate = Calendar.getInstance();
                    nowDate.setTime(new Date());
                    String balancetime = getBankConfig().getValueAsString("balancetime");
                    if ("".equals(balancetime) || balancetime == null) {
                        balancetime = "1";
                    }
                    nowDate.add(Calendar.HOUR_OF_DAY, -Integer.parseInt(balancetime));
                    //根据余额信息产生的时间(是否在1小时之内产生的)，是否需要生成新的余额查询请求文件
                    isCheckBalance = nowDate.getTimeInMillis() <= generatedDate.getTime();
                }//增加计数

                if (!isCheckBalance&&!isok) {
                    batchNum++;
                    /*
                     * 31,CN,501510443660,CNY,01/05/2012,02/06/2012,N
                     */
                    //生成余额查询文件
                    StringBuilder sb = new StringBuilder();
                    String reqSeqIdNew = reqSeqId + String.format("%3s", batchNum).replace(" ", "0");
                    if (reqSeqIdNew.length() > 10) {
                        reqSeqIdNew = reqSeqIdNew.substring(reqSeqIdNew.length() - 10, reqSeqIdNew.length());
                    }
                    sb.append(reqSeqIdNew);
                    sb.append(",");
                    //默认中国
                    sb.append("CN");
                    sb.append(",");
                    sb.append(actNum);
                    sb.append(",");
                    //默认人民币
                    sb.append(actCur);
                    sb.append(",");
                    String date = sdf.format(new Date());
                    sb.append(date);
                    sb.append(",");
                    sb.append(date);
                    sb.append(",");
                    //不查询余额明细
                    sb.append("N");
                    //生成余额请求文件到备份目录的路径
                    String bakDirectory = getDataFileDirectory(new Date()) + File.separator + "reqbalancebak\\";
                    String bakfullName = getTrimPath(bakDirectory) + File.separator + reqSeqIdNew + ".csv";
                    //生成scv文件保存到指定目录
                    boolean genCsvResult = writeFile(bakfullName, sb.toString(), getCharset());
                    if (genCsvResult) {
                        //do nothing;
                        if (copyFile(bakfullName, balanceRequestPath)) {//将生成的scv文件保存到本地，成功则返回true
                            WriteBankUrlLogLn(balanceRequestPath);
                            WriteBankLogStep2(sb);
//                            detail.respInfo = "未查到今日余额信息，已生成余额查询请求，请30分钟后再次进行查询。";
//                            detail.respCode = "-1";
                            detail.respCode = "0";
//                            retAts.writeRetDetail(detail, p_req7506.isBatch);
//                            continue;
                        } else {
                            detail.respInfo = "余额查询：账号" + actNum + "拷贝余额查询文件到指定目录失败！";
                            detail.respCode = "-1";
                            retAts.writeRetDetail(detail, p_req7506.isBatch);
                            continue;
                        }
                    } else {
                        detail.respInfo = "余额查询：账号" + actNum + "生成余额查询请求查询文件失败！";
                        detail.respCode = "-1";
                        retAts.writeRetDetail(detail, p_req7506.isBatch);
                        continue;
                    }
                }

                if (StringHelper.isNullOrEmpty(lastTranDate)) {
                    //余额报文应该怎么返回
                    detail.respCode = "-1";
                    detail.respInfo = "账号:" + actNum + "未查到今日余额信息，已生成余额查询请求，请30分钟后再次进行查询";
                    retAts.writeRetDetail(detail, p_req7506.isBatch);
                    continue;
                } else {
                    /*
                     * "BAL","31","GHK00001","CN","SCBLCNSXSHA","501510443660","CNY","02/05/2012","02/06/2012","01/06/2012",
                     * 0,562781.99,0,30090,"25/06/2012 18:52:31+0800",""
                     */
                    //冻结余额
                    DecimalFormat df = new DecimalFormat("0.00");
                    String frozenBal = "0.00";
                    BigDecimal currBalBig = new BigDecimal(currBal);
                    BigDecimal availBalBig = new BigDecimal(availBal);
                    if (!StringHelper.isNullOrEmpty(currBal) && !StringHelper.isNullOrEmpty(availBal)) {
                        if ((Double.parseDouble(currBal) - Double.parseDouble(availBal)) >= 0) {
                            BigDecimal frozen = currBalBig.subtract(availBalBig);
                            frozenBal = df.format(frozen);
                        }
                    }
                    //向detail对象赋值
                    detail.respCode = "0";
                    detail.actCur = actCur;
                    detail.actNum = actNum;
                    detail.availBal = df.format(availBalBig);
                    detail.frozenBal = frozenBal;
                    detail.currBal = df.format(currBalBig);
                    detail.respInfo = "";
                    //将detail对象写入 RetAts对象
                    retAts.writeRetDetail(detail, p_req7506.isBatch);
                }
            } catch (Exception ex) {
                detail.respCode = "-1";
                detail.respInfo = "账号:" + actNum + "查询今日余额信息异常:" + ex.getMessage();
                retAts.writeRetDetail(detail, p_req7506.isBatch);
                WriteBankLogLn("账号:" + actNum + "查询今日余额信息异常:" + ex.getMessage());
                continue;
            }
        }
        retAts.writeEnd();
        return retAts;
    }

    /**
     * 渣打银行历史余额查询
     * C#版本转java
     */
    @Override
    public RetAts7505HisBalQry d_7505_BalQry(Req7505HisBalQry p_req7505) throws Exception {

        //创建返回对象
        RetAts7505HisBalQry retAts = new RetAts7505HisBalQry(p_req7505.reqHeader);
        //写返回ATS的统一头部信息
        retAts.writeStart();
        //待查询账号
        String actNum = p_req7505.actNum;
        String reqSeqId = p_req7505.reqHeader.transSeqID;
        String actCur = convertCurToBank(p_req7505.actCur);
        try {
            //读取配置文件CSV文件导出的路径 xue
            //历史余额查询路径D:\Workspaces\FilesForDevelop\BankPort\SCB02\host2host\documents\reportscust\in\rpt\
            String balanceFilePath = getH2HPath("ReceiveSCBPriorDayDetailsFilePath");
            //D:\Workspaces\SCB02\reportscust\in\rpt\
            String localTxnFile = getH2HPath("localTxnFilePath");
            //<group id>.REPORTSCUST.<yyyymmddhhmmssXX>.<filesize>.txn
            //e.g. GCNA5011.REPORTSCUST.20140912130222VE.10229.txn
            //拷贝文件到本地路径
            folderToFolder(balanceFilePath, localTxnFile);
            //昨日余额查询
            Calendar calendarFrom = Calendar.getInstance();
            calendarFrom.setTime(p_req7505.getDateFrom());
            Calendar calendarTo = Calendar.getInstance();
            calendarTo.setTime(p_req7505.getDateTo());
            if (calendarTo.getTime().getTime() > System.currentTimeMillis()) {
                calendarTo.setTime(new Date());
            }
            Calendar amonthago = Calendar.getInstance();
            amonthago.setTime(new Date());
            //余额查询范围日期允许最大31天   MT940查询其实没限制
            amonthago.add(Calendar.MONTH, -1);
            if (calendarFrom.getTime().getTime() < amonthago.getTime().getTime()) {
                calendarFrom = amonthago;
            }
            //List<String[]> prebalances = new ArrayList<>();
            //存放历时余额详情Map Key为日期yyyy-MM-dd ,Value为当日余额
            int numOfDate = calendarTo.get(Calendar.DAY_OF_YEAR) - calendarFrom.get(Calendar.DAY_OF_YEAR) + 1;
            Map<String, String> prebalances = new HashMap<String, String>();
            for (int x = 0; x < numOfDate; x++) {
                prebalances.put(Format.Date10Format.format(calendarFrom.getTime()), "");
                calendarFrom.add(Calendar.DAY_OF_YEAR, 1);
            }
            for (Map.Entry<String, String> history : prebalances.entrySet()) {
                //指定日期路径yyyy-MM-dd
                String fileDatePath = getTrimPath(localTxnFile) + File.separator + history.getKey().substring(0, 4) + history.getKey().substring(5, 7) + File.separator + history.getKey().substring(8, 10);
                List<String> fileNames = getDirectoryAllFileName(fileDatePath);
                //region 解析查询日期条件范围内的每日余额信息
                for (String fileName : fileNames) {
                    String alltext = "";
                    synchronized (this) {
                        //读取文件内容
                        alltext = FileHelper.readFileText(getTrimPath(fileDatePath) + File.separator + fileName, getCharset());
                    }
                    //对单个文件进行解析查找对应的账号明细信息 //"H", 明细头记录拆分符
                    String[] sArray1 = alltext.split(":25:");
                    if (sArray1.length > 1 && sArray1[1].startsWith(actNum)) {
                        //获取openingBalance
                        DecimalFormat df = new DecimalFormat("0.00");
                        String[] balanceArray = sArray1[1].split(":62F:");
                        if (balanceArray.length > 1) {
                            String cdFlag = balanceArray[1].substring(0, 1);
                            String amt = balanceArray[1].substring(10, balanceArray[1].indexOf("\r\n"));
                            convertCommaToPoint(amt);
                            if ("D".equals(cdFlag)) {
                                amt = "-" + amt;
                            }
                            history.setValue(amt);
                            break;
                        }
                    }
                }
            }

            List<String> detailsNotExists = new ArrayList<String>();
            for (Map.Entry<String, String> history : prebalances.entrySet()) {
                //找出没有历史余额的日期
                if ("".equals(history.getValue())) {
                    detailsNotExists.add(history.getKey());
                }
            }

            //如果某一天没有余额信息则生成余额查询文件进行查询
            //如果查询的日结中不包含某日的历史余额，则在当日余额信息中查询已请求的某日余额信息，如果还是不存在则生成余额查询请求文件
            if (detailsNotExists.size() > 0) {
                //今日余额查询路径
                //D:\Workspaces\FilesForDevelop\BankPort\SCB02\host2host\documents\reportscust\in\txn\
                balanceFilePath = getH2HPath("ReceiveSCBTodayBalanceFilePath");
                //D:\Workspaces\SCB02\reportscust\in\txn\
                String localBalFile = getH2HPath("localBalFilePath");
                //<group id>.REPORTSCUST.<yyyymmddhhmmssXX>.<filesize>.txn
                //e.g. GCNA5011.REPORTSCUST.20140912130222VE.10229.txn
                //拷贝文件到本地路径
                String flag = getBankConfig().getValueAsString("copyFileNotDir");
                if ("false".equals(flag)) {
                    folderToFolder(balanceFilePath, localBalFile, 7515);
                } else {
                    folderToFolder(balanceFilePath, localBalFile);
                }


                int m = 0;
                //余额查询请求路径
                String balanceRequestPath = getH2HPath("BalanceRequestFilePath");
                //checkDate yyyyMMdd
                for (String checkDate : detailsNotExists) {
                    //当前余额
                    String currBal = "0.00";
                    //可用余额
                    String availBal = "0.00";
                    //交易余额日期
                    String lastTranDate = "";
                    Calendar queryDate = Calendar.getInstance();
                    queryDate.setTime(new Date());
                    //查找七天内查询结果文件
                    for (int i = 0; i <= 7; i++) {
                        try {
                            String date = Format.Date8Format.format(queryDate.getTime());
                            String fileDatePath = getTrimPath(localBalFile) + File.separator + File.separator + date.substring(0, 6) + File.separator + date.substring(6, 8);
                            queryDate.add(Calendar.DAY_OF_YEAR, -1);
                            List<String> filenamelist = getDirectoryAllFileName(fileDatePath);
                            for (String filename : filenamelist) {
                                synchronized (this) {
                                    String strline = FileHelper.readFileText(getTrimPath(fileDatePath) + File.separator + filename, getCharset());
                                    String[] aryline = splitStringWithComma(strline);
                                    if (aryline.length > 13) {
                                        String formatedDate = sdf.format(Format.Date10Format.parse(checkDate));
                                        if ("BAL".equals(aryline[0]) && aryline[5].equals(actNum) && aryline[9].equals(formatedDate)) {
                                            lastTranDate = aryline[9];
                                            currBal = aryline[11];
                                            availBal = aryline[13];
                                        }
                                    } else {
                                        WriteBankLogLn("账号余额查询：" + filename + "文件中余额信息格式不正确！");
                                    }
                                }
                            }
                        } catch (Exception e) {
                            WriteBankLogLn(e);
                        }
                    }

                    if (!StringHelper.isNullOrEmpty(lastTranDate)) {
                        prebalances.put(Format.Date10Format.format(sdf.parse(lastTranDate)), currBal);
                    } else {
                        m++;
                        //生成余额查询请求查询文件
                        StringBuilder sb = new StringBuilder();
                        String reqSeqIdNew = reqSeqId + String.format("%3s", m).replace(" ", "0");
                        if (reqSeqIdNew.length() > 10) {
                            reqSeqIdNew = reqSeqIdNew.substring(reqSeqIdNew.length() - 10, reqSeqIdNew.length());
                        }
                        sb.append(reqSeqIdNew);
                        sb.append(",");
                        //默认中国
                        sb.append("CN");
                        sb.append(",");
                        sb.append(actNum);
                        sb.append(",");
                        //默认人民币
                        sb.append(actCur);
                        sb.append(",");
                        //yyyy-MM-dd---->dd/MM/yyyy
                        String dateFormat = checkDate.substring(8, 10) + "/" + checkDate.substring(5, 7) + "/" + checkDate.substring(0, 4);
                        sb.append(dateFormat);
                        sb.append(",");
                        sb.append(dateFormat);
                        sb.append(",");
                        //不查询余额明细
                        sb.append("N");
                        //生成scv文件保存到指定目录
                        //生成余额请求文件到备份目录的路径
                        String bakDirectory = getDataFileDirectory(new Date()) + File.separator + "reqbalancebak\\";
                        String bakfullName = getTrimPath(bakDirectory) + File.separator + reqSeqIdNew + ".csv";
                        //生成scv文件保存到指定目录
                        boolean genCsvResult = writeFile(bakfullName, sb.toString(), getCharset());
                        if (genCsvResult) {
                            if (copyFile(bakfullName, balanceRequestPath)) {
                                WriteBankUrlLogLn(balanceRequestPath);
                                WriteBankLogStep2(sb);
                                if (!retAts.hasWrittenRespInfo) {
                                    retAts.writeRespInfo("部分未查询到的结果已生成查询文件查询");
                                }
                            }
                        }

                    }
                }
            }
            for (Map.Entry<String, String> history : prebalances.entrySet()) {
                RetAtsHisBalDetail retDetail = new RetAtsHisBalDetail();
                //余额日期 yyyy-MM-dd
                retDetail.balDate = history.getKey();
                //历史余额、此余额是返回当前总余额还是当前可用余额
                retDetail.actBal = history.getValue();
                retAts.writeRetDetail(retDetail);
            }
        } catch (Exception e) {
            if (!retAts.hasWrittenRespCode) {
                retAts.writeRespCode("-1");
            }
            if (!retAts.hasWrittenRespInfo) {
                retAts.writeRespInfo(e.getMessage());
            }
            retAts.writeEnd();
            return retAts;
        }


        if (retAts.getWrittenRdCount() == 0) {
            if (!retAts.hasWrittenRespCode) {
                retAts.writeRespCode("-1");
            }
            if (!retAts.hasWrittenRespInfo) {
                retAts.writeRespInfo("返回结果为空，所查询时间段内不存在历史余额");
            }
            retAts.writeEnd();
            return retAts;
        }
        retAts.writeEnd();
        return retAts;
    }
}
